<?php

// @formatter:off
/**
 * @file DImagesCron.php
 * @author Alejandro Dario Simi
 * @date $Date: 2014-06-03 03:40:32 +0000 (Tue, 03 Jun 2014) $
 *
 * $Id: DImagesCron.php 112 2014-06-03 03:40:32Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/extensions/DuplicatedImages/includes/DImagesCron.php $
 */
// @formatter:on

include WC_E_DIMAGES_ROOTDIR."/includes/DImages.php";

class DImagesCron extends WCCronTool {
	protected static $_FingerprintsPerRun = 1000;
	//
	// Public methods.
	public function run($spacer = "") {
		global $wcOptions;

		$groupId = $wcOptions->activated("Group") ? $wcOptions->value("Group") : false;
		//		$verbose = $wcOptions->activated("Verbose");

		foreach(WCGroupsHolder::I()->items() as $group) {
			//
			// Ignoring not matching groups when there's a specified
			// one.
			if($groupId && $group->id != $groupId) {
				continue;
			}
			if(is_readable($group->root)) {
				echo "{$spacer}Analizing group '{$group}':\n";
				$this->loadNewImages($group, "{$spacer}\t");
				$this->removeDeadImages($group, "{$spacer}\t");
				$this->analizePendingImages($group, "{$spacer}\t");
				$this->generateMarks($group, "{$spacer}\t");
			}
		}
	}
	public function showHelp($spacer = "") {
		//echo "{$spacer}This tool adds tag '{self::$TagNoName}' to any comics without
		// tags.\n\n";
		echo "{$spacer}Options:\n";
		echo "{$spacer}\t-g group-id, --group group-id\n";
		echo "{$spacer}\t\tIt only for a specific group.\n\n";
		//		echo "{$spacer}\t-v, --verbose\n";
		//		echo "{$spacer}\t\tShows more information.\n\n";
	}
	//
	// Protected methods.
	protected function analizePendingImages(WCGroup &$group, $spacer) {
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  *\n";
			$query.= "from    {$this->_dbprefix}dimages\n";
			$query.= "where   dif_distance is null\n";
			$query.= " and    dif_group = :group\n";
			$query.= "order by dif_comic asc\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}
		//
		// @{
		$stmtU = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[U]";
		if($this->_db->has($stmtId)) {
			$stmtU = $this->_db->get($stmtId);
		} else {
			$query = "update  {$this->_dbprefix}dimages\n";
			$query.= "set     dif_fingerprint = :fingerprint,\n";
			$query.= "        dif_distance    = :distance,\n";
			$query.= "        dif_relation    = :relation\n";
			$query.= "where   dif_group = :group\n";
			$query.= " and    dif_comic = :comic\n";
			$query.= " and    dif_image = :image\n";

			$stmtU = $this->_db->prepare($stmtId, $query);
		}
		// @}
		if($stmt->execute(array(":group" => $group->id)) && $stmt->rowCount() > 0) {
			echo "{$spacer}Analizing pending images ({$stmt->rowCount()} images):\n";

			$manager = DImages::I();
			$imHolder = WCImagesHolder::I();
			$ciHolder = WCComicImagesHolder::I();
			$params = array(
				":fingerprint" => "",
				":distance" => "",
				":relation" => "",
				":group" => $group->id,
				":comic" => "",
				":image" => ""
			);

			$count = $stmt->rowCount() > self::$_FingerprintsPerRun ? self::$_FingerprintsPerRun : $stmt->rowCount();

			$image = false;
			$lastExpanded = 0;
			foreach($stmt->fetchAll() as $row) {
				$params[":image"] = $row["dif_image"];
				$params[":comic"] = $row["dif_comic"];

				if($row["dif_fingerprint"] && $row["dif_relation"]) {
					$count++;
					printf("{$spacer}\t[----] Quick analysis of fingerprint '%s': ", $row["dif_fingerprint"]);

					$info = $manager->getFingerprint("nopath", $row["dif_fingerprint"], $row["dif_relation"]);
					if($info["status"]) {
						echo "\n";
						echo "{$spacer}\t\tFingerprint: ".WCColorText::ShellYellow($info["fingerprint"])."\n";
						echo "{$spacer}\t\tDistance:    ".WCColorText::ShellGreen($info["distance"])."\n";
						echo "{$spacer}\t\tRelation:    {$info["relation"]}\n";
						echo "{$spacer}\t\tTime:        ".WCColorText::ShellPurple("{$info["time"]}ms")."\n";

						$params[":fingerprint"] = $info["fingerprint"];
						$params[":distance"] = $info["distance"];
						$params["relation"] = $info["relation"];

						$stmtU->execute($params);
					} else {
						echo WCColorText::ShellRed("Failed").": unable to calculate finguerprint.\n";
					}
				} else {
					if($row["dif_comic"]) {
						if($image && $lastExpanded && $row["dif_comic"] != $lastExpanded) {
							$image->shrink();
						}
						$image = $ciHolder->item($row["dif_image"]);
						$image->expand();
						$lastExpanded = $row["dif_comic"];
					} else {
						$image = $imHolder->item($row["dif_image"]);
					}
					if($image && $image->ok()) {
						printf("{$spacer}\t[% 4d] Analizing image '%s': ", $count, (string) $image);

						$info = $manager->getFingerprint($image->path());
						if($info["status"]) {
							echo "\n";
							echo "{$spacer}\t\tFingerprint: ".WCColorText::ShellYellow($info["fingerprint"])."\n";
							echo "{$spacer}\t\tDistance:    ".WCColorText::ShellGreen($info["distance"])."\n";
							echo "{$spacer}\t\tRelation:    {$info["relation"]}\n";
							echo "{$spacer}\t\tMD5:         {$image->md5}\n";
							echo "{$spacer}\t\tTime:        ".WCColorText::ShellPurple("{$info["time"]}ms")."\n";

							$params[":fingerprint"] = $info["fingerprint"];
							$params[":distance"] = $info["distance"];
							$params["relation"] = $info["relation"];

							$stmtU->execute($params);
						} else {
							echo WCColorText::ShellRed("Failed").": unable to calculate finguerprint.\n";
						}
					}
				}

				$count--;

				if($count <= 0) {
					break;
				}
			}

			if($image && $lastExpanded) {
				$image->shrink();
			}
		}
	}
	protected function generateMarks(WCGroup &$group, $spacer) {
		echo "{$spacer}Removing old marks: ";
		//
		// @{
		$stmtT = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[T]";
		if($this->_db->has($stmtId)) {
			$stmtT = $this->_db->get($stmtId);
		} else {
			$query = "delete from {$this->_dbprefix}dimages_dups\n";
			$query.= "where       did_group = :group\n";

			$stmtT = $this->_db->prepare($stmtId, $query);
		}
		// @}
		$stmtT->execute(array(
			":group" => $group->id
		));
		echo WCColorText::ShellGreen($stmtT->rowCount()."\n");

		echo "{$spacer}Generating duplicated marks: ";
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[I]";
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "insert ignore\n";
			$query.= "        into {$this->_dbprefix}dimages_dups(did_group, did_type, did_value)\n";
			$query.= "        (\n";
			$query.= "                select  dif_group,\n";
			$query.= "                        'D',\n";
			$query.= "                        dif_distance\n";
			$query.= "                from    {$this->_dbprefix}dimages\n";
			$query.= "                where   dif_group = :group\n";
			$query.= "                group by dif_distance\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        ) union all (\n";
			$query.= "                select  dif_group,\n";
			$query.= "                        'F',\n";
			$query.= "                        dif_fingerprint\n";
			$query.= "                from    {$this->_dbprefix}dimages\n";
			$query.= "                where   dif_group = :group\n";
			$query.= "                group by dif_fingerprint\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        ) union all (\n";
			$query.= "                select  img_group,\n";
			$query.= "                        '5',\n";
			$query.= "                        img_md5\n";
			$query.= "                from    {$this->_dbprefix}images\n";
			$query.= "                where   img_group =  :group\n";
			$query.= "                 and    img_lost  =  'N'\n";
			$query.= "                 and    img_md5   <> ''\n";
			$query.= "                group by img_md5\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        ) union all (\n";
			$query.= "                select  cim_group,\n";
			$query.= "                        '5',\n";
			$query.= "                        cim_md5\n";
			$query.= "                from    {$this->_dbprefix}comic_images\n";
			$query.= "                where   cim_group =  :group\n";
			$query.= "                 and    cim_lost  =  'N'\n";
			$query.= "                 and    cim_md5   <> ''\n";
			$query.= "                group by cim_md5\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        ) union all (\n";
			$query.= "                select  img_group,\n";
			$query.= "                        'S',\n";
			$query.= "                        img_sha1\n";
			$query.= "                from    {$this->_dbprefix}images\n";
			$query.= "                where   img_group =  :group\n";
			$query.= "                 and    img_lost  =  'N'\n";
			$query.= "                 and    img_sha1  <> ''\n";
			$query.= "                group by img_sha1\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        ) union all (\n";
			$query.= "                select  cim_group,\n";
			$query.= "                        'S',\n";
			$query.= "                        cim_sha1\n";
			$query.= "                from    {$this->_dbprefix}comic_images\n";
			$query.= "                where   cim_group =  :group\n";
			$query.= "                 and    cim_lost  =  'N'\n";
			$query.= "                 and    cim_sha1  <> ''\n";
			$query.= "                group by cim_sha1\n";
			$query.= "                having count(1) > 1\n";
			$query.= "        )\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}
		$stmt->execute(array(
			":group" => $group->id
		));
		echo WCColorText::ShellGreen($stmt->rowCount())."\n";
	}
	protected function loadNewImages(WCGroup &$group, $spacer) {
		echo "{$spacer}Loading new images: ";
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "insert ignore\n";
			$query.= "        into {$this->_dbprefix}dimages(dif_group, dif_comic, dif_image)\n";
			$query.= "        (\n";
			$query.= "                select  img_group,\n";
			$query.= "                        0,\n";
			$query.= "                        img_id\n";
			$query.= "                from    {$this->_dbprefix}images\n";
			$query.= "                where   img_group = :group\n";
			$query.= "                 and    img_lost  = 'N'\n";
			$query.= "        ) union all (\n";
			$query.= "                select  cim_group,\n";
			$query.= "                        cim_comic,\n";
			$query.= "                        cim_id\n";
			$query.= "                from    {$this->_dbprefix}comic_images\n";
			$query.= "                where   cim_group = :group\n";
			$query.= "                 and    cim_lost  = 'N'\n";
			$query.= "        )\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$stmt->execute(array(
			":group" => $group->id
		));

		echo WCColorText::ShellGreen($stmt->rowCount())."\n";
	}
	protected function loadOptions() {
		if(!$this->_optionsLoaded) {
			global $wcOptions;

			if($wcOptions->addValueOption("Group")) {
				$wcOptions->addOptionTrigger("Group", "g");
				$wcOptions->addOptionTrigger("Group", "group");
			}

			$wcOptions->check();

			$this->_optionsLoaded = true;
		}
	}
	protected function removeDeadImages(WCGroup &$group, $spacer) {
		echo "{$spacer}Removing dead images: ";
		//
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__;
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "delete from {$this->_dbprefix}dimages\n";
			$query.= "where       (dif_group = :group and dif_comic = 0 and dif_image not in (\n";
			$query.= "                    select  img_id\n";
			$query.= "                    from    {$this->_dbprefix}images\n";
			$query.= "                    where   img_group = :group\n";
			$query.= "                     and    img_lost  = 'N')\n";
			$query.= "            )\n";
			$query.= " or         (dif_group = :group and dif_comic <> 0 and (dif_comic,dif_image) not in (\n";
			$query.= "                    select  cim_comic, cim_id\n";
			$query.= "                    from    {$this->_dbprefix}comic_images\n";
			$query.= "                                    inner join {$this->_dbprefix}comics\n";
			$query.= "                                            on(cmc_id = cim_comic)\n";
			$query.= "                    where   cim_group = :group\n";
			$query.= "                     and    cim_lost  = 'N'\n";
			$query.= "                     and    cmc_lost  = 'N')\n";
			$query.= "            )\n";

			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}

		$stmt->execute(array(
			":group" => $group->id
		));

		echo WCColorText::ShellGreen($stmt->rowCount()."\n");
	}
}
